package drds.plus.sql_process.utils.range;

import drds.plus.sql_process.abstract_syntax_tree.ObjectCreateFactory;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.Item;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.BooleanFilter;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Filter;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Operation;
import drds.plus.sql_process.type.Type;
import drds.plus.sql_process.type.Types;
import drds.plus.sql_process.utils.DnfFilters;

import java.util.ArrayList;
import java.util.List;

public abstract class AbstractRangeProcessor {

    /**
     * 处理下filter
     */
    public abstract boolean process(Filter filter);

    /**
     * 构造Range对象
     */
    protected Range getRange(Filter filter) {
        if (!(filter instanceof BooleanFilter)) {
            return null;
        }

        BooleanFilter booleanFilter = (BooleanFilter) filter;
        if (DnfFilters.isConstantFilter(booleanFilter)) {
            return null;
        }

        if (filter.getOperation() == Operation.in) {
            // 不处理null
            return null;
        }

        Type type = getColumn(booleanFilter).getType();
        if (type == null) {
            type = Types.getTypeOfObject(booleanFilter.getValue());
        }

        if (!isNumberType(type)) {
            // 只处理数字类型，避免时间戳类型的合并
            return null;
        }

        switch (booleanFilter.getOperation()) {
            case equal:
                return new Range(null, type, getValue(booleanFilter), getValue(booleanFilter));
            case greater_than:
                return new Range(null, type, getValue(booleanFilter), false, null, true);
            case greater_than_or_equal:
                return new Range(null, type, getValue(booleanFilter), true, null, true);
            case less_than:
                return new Range(null, type, null, true, getValue(booleanFilter), false);
            case less_than_or_equal:
                return new Range(null, type, null, true, getValue(booleanFilter), true);
            default:
                return null;
        }

    }

    protected boolean isNumberType(Type type) {
        if (type == null) {
            return false;
        }
        // 保持这样的优先级执行速度快
        return type == Type.IntegerType || type == Type.LongType || type == Type.BigDecimalType || type == Type.BigIntegerType || type == Type.ShortType;
    }

    protected Comparable getValue(BooleanFilter booleanFilter) {
        return (Comparable) booleanFilter.getValue();
    }

    protected Item getColumn(BooleanFilter booleanFilter) {
        return (Item) booleanFilter.getColumn();
    }

    /**
     * 根据range结果，构造filter
     */
    protected List<Filter> buildFilterList(Range range, Object column) {
        List<Filter> filterList = new ArrayList(2);
        if (range == null) {
            return filterList;
        }
        if (range.isSingleValue()) {
            BooleanFilter booleanFilter = ObjectCreateFactory.createBooleanFilter();
            booleanFilter.setOperation(Operation.equal);
            booleanFilter.setColumn(column);
            booleanFilter.setValue(range.getMaxValue());
            filterList.add(booleanFilter);
            return filterList;
        }

        if (range.getMinValue() != null) {
            BooleanFilter booleanFilter;
            if (range.isMinIncluded()) {
                booleanFilter = ObjectCreateFactory.createBooleanFilter();
                booleanFilter.setOperation(Operation.greater_than_or_equal);
            } else {
                booleanFilter = ObjectCreateFactory.createBooleanFilter();
                booleanFilter.setOperation(Operation.greater_than);
            }

            booleanFilter.setColumn(column);
            booleanFilter.setValue(range.getMinValue());
            filterList.add(booleanFilter);
        }

        if (range.getMaxValue() != null) {
            BooleanFilter booleanFilter;
            if (range.isMaxIncluded()) {
                booleanFilter = ObjectCreateFactory.createBooleanFilter();
                booleanFilter.setOperation(Operation.less_than_or_equal);
            } else {
                booleanFilter = ObjectCreateFactory.createBooleanFilter();
                booleanFilter.setOperation(Operation.less_than);
            }

            booleanFilter.setColumn(column);
            booleanFilter.setValue(range.getMaxValue());
            filterList.add(booleanFilter);
        }
        return filterList;
    }
}
